﻿using System;
using System.Data.Common;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Services;
using Dexter.Web.Core;
using Dexter.Web.Mvc.Filters;
using Dexter.Web.Mvc.ViewModel.Backoffice.Binders;
using Dexter.Web.Mvc.ViewModel.Backoffice.ViewsData.SetupController;
using Dexter.Web.Routing;

namespace Dexter.Web.Mvc.Controllers.Backoffice {
	[DexterCallFilter ( false )]
	public class SetupController : Controller {
		readonly IHostEnvironment hostEnvironment;
		readonly ILogger logger;
		readonly IRoutingService routingService;
		readonly ISetupService setupService;
		readonly IUrlBuilder urlBuilder;

		/// <summary>
		/// 	Initializes a new instance of the <see cref = "SetupController" /> class.
		/// </summary>
		/// <param name = "setupService">The setup service.</param>
		/// <param name = "urlBuilder">The URL builder.</param>
		/// <param name = "logger">The logger.</param>
		public SetupController ( ISetupService setupService , IUrlBuilder urlBuilder , ILogger logger , IRoutingService routingService , IHostEnvironment hostEnvironment ) {
			this.setupService = setupService;
			this.urlBuilder = urlBuilder;
			this.logger = logger;
			this.routingService = routingService;
			this.hostEnvironment = hostEnvironment;
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult Wizard ( ) {
			var data = new WizardViewData ( );
			data.Setup = new SetupBinder ( );
			data.Setup.TimeZone = "UTC";
			if ( HttpContext.Request.UserLanguages != null && HttpContext.Request.UserLanguages.Length > 0 ) {
				data.Setup.CultureInfo = HttpContext.Request.UserLanguages[ 0 ];
			}

			data.TimesZone = TimeZoneInfo.GetSystemTimeZones ( );
			data.Languages = new[] {"Danish" , "Dutch" , "English" , "Finnish" , "French" , "German2" , "German" , "Italian" , "Kp" , "Lovins" , "Norwegian" , "Porter" , "Portuguese" , "Russian" , "Spanish" , "Swedish"};
			data.CultureInfos = CultureInfo.GetCultures ( CultureTypes.AllCultures );

			return View ( data );
		}

		[AcceptVerbs ( HttpVerbs.Post )]
		[ValidateAntiForgeryToken]
		public ActionResult Wizard ( SetupBinder setup ) {
			if ( !ModelState.IsValid ) {
				var data = new WizardViewData ( );
				data.Setup = setup;
				data.TimesZone = TimeZoneInfo.GetSystemTimeZones ( );
				data.Languages = new[] {"Danish" , "Dutch" , "English" , "Finnish" , "French" , "German2" , "German" , "Italian" , "Kp" , "Lovins" , "Norwegian" , "Porter" , "Portuguese" , "Russian" , "Spanish" , "Swedish"};
				data.CultureInfos = CultureInfo.GetCultures ( CultureTypes.AllCultures );

				return View ( data );
			}

			try {
				DbConnectionStringBuilder csb = new DbConnectionStringBuilder ( );
				csb.ConnectionString = setup.ConnectionString;
			}
			catch {
				ModelState.AddModelError ( "Invalid Connection String" , "The specified connection string is invalid" );

				var data = new WizardViewData ( );
				data.Setup = setup;
				data.TimesZone = TimeZoneInfo.GetSystemTimeZones ( );
				data.Languages = new[] {"Danish" , "Dutch" , "English" , "Finnish" , "French" , "German2" , "German" , "Italian" , "Kp" , "Lovins" , "Norwegian" , "Porter" , "Portuguese" , "Russian" , "Spanish" , "Swedish"};
				data.CultureInfos = CultureInfo.GetCultures ( CultureTypes.AllCultures );

				return View ( data );
			}

			try {
				SiteConfiguration sc = SiteConfiguration.GetDefaultConfiguration ( );
				sc.BlogName = setup.WebSiteName;
				sc.UrlBuilder.SiteDomain = setup.SiteDomain;
				sc.SiteLanguage = setup.Language;
				sc.TimeZone = TimeZoneInfo.FindSystemTimeZoneById ( setup.TimeZone );
				sc.Culture = CultureInfo.CreateSpecificCulture ( setup.CultureInfo );

				setupService.Inizialize ( sc , setup.CreateDatabase , setup.ConnectionString , setup.Username , setup.Password , setup.Email , setup.DatabaseType , setup.DatabaseSchema , setup.DatabaseTablePrefix );

				routingService.UpdateRoutes ( );

				FormsAuthentication.SetAuthCookie ( setup.Username , false );

				return RedirectToAction ( "SetupComplete" );
			}
			catch ( Exception exc ) {
				logger.Fatal ( exc.Message , exc );
				ModelState.AddModelError ( "Something wring!" , exc.ToString ( ) );

				var data = new WizardViewData ( );
				data.Setup = setup;
				data.TimesZone = TimeZoneInfo.GetSystemTimeZones ( );
				data.Languages = new[] {"Danish" , "Dutch" , "English" , "Finnish" , "French" , "German2" , "German" , "Italian" , "Kp" , "Lovins" , "Norwegian" , "Porter" , "Portuguese" , "Russian" , "Spanish" , "Swedish"};
				data.CultureInfos = CultureInfo.GetCultures ( CultureTypes.AllCultures );

				return View ( data );
			}
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult SetupComplete ( ) {
			hostEnvironment.RestartAppDomain ( );
			return Redirect ( urlBuilder.HomePage.ToString ( ) );
		}
	}
}